# -*- coding: utf-8 -*-
"""
@Time: 2025/1/10 11:42
@Auth: Zhang Hongxing
@File: ocr_routes.py
@Note: 输入形式多样化服务相关路由
"""
from flask import Blueprint, request, jsonify
from services.ocr_service import upload_text, upload_image, upload_pdf, save_essay_text
from backend.services.analysis_service import preprocess_text
from backend.services.user_service import get_user_profile
from functools import wraps
import jwt
from datetime import datetime

ocr_routes = Blueprint('ocr_routes', __name__)

# 配置信息
SECRET_KEY = 'your_secret_key'
TOKEN_EXPIRATION = 24 * 60 * 60  # 24小时过期


def decode_token(token):
    """
    解码JWT令牌
    """
    try:
        # 明确指定算法和验证选项
        payload = jwt.decode(
            token,
            SECRET_KEY,
            algorithms=['HS256'],
            options={
                'verify_exp': True,  # 验证过期时间
                'verify_iat': True,  # 验证签发时间
            }
        )
        return payload
    except jwt.ExpiredSignatureError:
        print("令牌已过期")
        return None
    except jwt.InvalidTokenError as e:
        print(f"无效的令牌: {str(e)}")
        return None
    except Exception as e:
        print(f"令牌解析错误: {str(e)}")
        return None


def token_required(f):
    """
    Token验证装饰器
    """

    @wraps(f)
    def decorated(*args, **kwargs):
        # 获取Authorization头
        auth_header = request.headers.get('Authorization')
        if not auth_header:
            return jsonify({
                "code": 401,
                "message": "缺少Authorization头信息"
            }), 401

        # 验证Bearer格式
        parts = auth_header.split()
        if parts[0].lower() != 'bearer' or len(parts) != 2:
            return jsonify({
                "code": 401,
                "message": "无效的Authorization格式"
            }), 401

        token = parts[1]
        payload = decode_token(token)

        if payload is None:
            return jsonify({
                "code": 401,
                "message": "无效或过期的令牌"
            }), 401

        try:
            # 验证令牌中的必要信息
            if 'user_id' not in payload:
                return jsonify({
                    "code": 401,
                    "message": "令牌缺少用户信息"
                }), 401

            # 验证令牌是否过期
            exp_timestamp = payload.get('exp')
            if exp_timestamp is None:
                return jsonify({
                    "code": 401,
                    "message": "令牌缺少过期时间"
                }), 401

            current_timestamp = datetime.utcnow().timestamp()
            if current_timestamp > exp_timestamp:
                return jsonify({
                    "code": 401,
                    "message": "令牌已过期"
                }), 401

            # 将用户信息添加到请求上下文
            return f(payload['user_id'], *args, **kwargs)

        except Exception as e:
            return jsonify({
                "code": 401,
                "message": f"令牌验证失败: {str(e)}"
            }), 401

    return decorated


# 【接口2.1.1】POST /essay/submit/text    # 提交作文文本
@ocr_routes.route('/essay/submit/text', methods=['POST'])
@token_required
def submit_text(user_id):
    """
    接收用户提交的作文标题和文本内容，并保存为JSON格式的文件
    """
    try:
        # 验证请求格式
        if not request.is_json:
            return jsonify({
                "code": 400,
                "message": "请求必须是JSON格式"
            }), 400

        data = request.get_json()
        title = data.get('title')
        text = data.get('text')

        if not title or not isinstance(title, str):
            return jsonify({
                "code": 400,
                "message": "作文标题不能为空且必须是字符串"
            }), 400

        if not text or not isinstance(text, str):
            return jsonify({
                "code": 400,
                "message": "作文文本不能为空且必须是字符串"
            }), 400

        # 保存文本到文件
        success, essay_id, version_id = upload_text(user_id, title, text)

        if success:
            return jsonify({
                "code": 200,
                "message": "作文上传成功",
                "data": {
                    "user_id": user_id,
                    "essay_id": essay_id,
                    "version_id": version_id,
                    "title": title,
                    "text": text,
                    "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                }
            }), 200
        else:
            return jsonify({
                "code": 500,
                "message": "作文上传失败"
            }), 500

    except Exception as e:
        return jsonify({
            "code": 500,
            "message": f"服务器错误: {str(e)}"
        }), 500


# 【接口2.1.2】POST /essay/submit/file    # 提交作文图片/文件
@ocr_routes.route('/essay/submit/file', methods=['POST'])
@token_required
def submit_file(user_id):
    """
    接收用户上传的图片、PDF 或 DOC/DOCX 文件，并保存，同时提取文本，并存储到 essay_data 目录
    """
    try:
        # 验证文件是否存在
        if 'file' not in request.files or 'title' not in request.form:
            return jsonify({"code": 400, "message": "请求中未包含文件或标题"}), 400

        file = request.files['file']
        title = request.form['title'].strip()

        # 验证标题
        if not title:
            return jsonify({"code": 400, "message": "作文标题不能为空"}), 400

        # 验证文件名
        if file.filename == '':
            return jsonify({"code": 400, "message": "未选择文件"}), 400

        # 获取文件扩展名
        file_ext = file.filename.rsplit('.', 1)[1].lower()
        allowed_extensions = {'png', 'jpg', 'jpeg', 'pdf'}
        if file_ext not in allowed_extensions:
            return jsonify({"code": 400, "message": "不支持的文件格式，仅支持 PNG、JPG、JPEG和PDF "}), 400

        # 验证用户信息
        user = get_user_profile(user_id)
        if not user:
            return jsonify({"code": 404, "message": "用户信息不存在"}), 404

        # 处理文件上传
        if file_ext in {'png', 'jpg', 'jpeg'}:
            file_path, recognized_text = upload_image(file, user_id)
            file_type = "image"
        elif file_ext == 'pdf':
            file_path, recognized_text = upload_pdf(file, user_id)
            file_type = "pdf"

        if file_path:
            # 存储识别文本到 JSON 文件
            success, essay_id, version_id = save_essay_text(user_id, title, recognized_text)

            return jsonify({
                "code": 200,
                "message": f"{file_type.upper()} 上传成功",
                "data": {
                    "file_path": file_path,
                    "file_type": file_type,
                    "file_ext": file_ext,
                    "user_id": user_id,
                    "essay_id": essay_id,
                    "version_id": version_id,
                    "title": title,
                    "recognized_text": recognized_text,
                    "upload_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                }
            }), 200
        else:
            return jsonify({"code": 500, "message": f"{file_type.upper()} 上传失败"}), 500

    except Exception as e:
        print(f"文件上传错误: {str(e)}")
        return jsonify({"code": 500, "message": f"服务器处理文件时出错: {str(e)}"}), 500


# 【接口3.1.2】POST /model/preprocess  文本预处理
@ocr_routes.route('/model/preprocess', methods=['POST'])
@token_required  # 添加token验证装饰器
def preprocess_text_api(user_id: str):
    """
    文本预处理 API
    :return: 返回预处理后的单词列表（JSON格式）
    """
    try:
        # 获取请求中的文本参数
        data = request.get_json()
        text = data.get('text')

        if not text:
            return jsonify({"code": 400, "message": "缺少文本参数"}), 400

        # 调用文本预处理服务
        processed_text = preprocess_text(text)

        # 如果预处理失败
        if processed_text is None:
            return jsonify({"code": 500, "message": "文本预处理失败"}), 500

        # 返回成功响应，包含预处理后的数据
        return jsonify({
            "code": 200,
            "message": "文本预处理成功",
            "data": processed_text
        }), 200

    except Exception as e:
        # 捕获异常并返回服务器错误
        print(f"【接口3.1.2】文本预处理失败: {e}")
        return jsonify({"code": 500, "message": "服务器内部错误"}), 500
